Organizations環境下で AWS Security Hubのコントロール無効化を自動化する
【2023/07/10 追記】
現在は Security Hub コントロール無効化の仕組みを、より簡単に作成できるようになっております。
本ブログではなく、以下を参照ください。
はじめに
マルチアカウント環境な Security Hub を運用していく際に 大変になってくるのが 特定コントロールの無効化 です。
コントロールの無効化操作は全アカウントそれぞれに対して行う必要があります (つまり 管理者側で無効化してもメンバー側には反映されない)。
この無効化作業を自動化する仕組みを考えてみました。
※ なお Control Tower環境の場合は以下のブログに紹介する通り、 カスタマイズソリューションを活用することで自動化できます。
想定する Security Hub 環境
以下土台は整っている前提とします。
- AWS Security Hub の Organizations 連携を活用している
- 全てのアカウントで 『AWS 基礎セキュリティのベストプラクティス v1.0.0』 が自動有効されるようになっている
※この土台作りの詳細は以下ブログを参照ください。
どんな仕組みを作るのか?
『基礎セキュリティのベストプラクティス』 の 特定コントロールを 自動無効化(有効化) する仕組みを作ります。 具体的には以下 2機能です。
- 特定OU配下アカウントの 特定コントロールを一括で無効化(有効化)する
- 新規アカウントが 特定 OUに所属したタイミングでも 自動で特定コントロールを無効化(有効化)する
どうやって作るのか?
以下ブログに紹介した『特定OUに所属したタイミングで Lambda を実行させる』 仕組みを活用します。(詳しい解説はこちら参照ください)
ざっくりと説明すると、 Lambda-backed カスタムリソースを展開する Organizations 連携のスタックセット を作成します。 これによりOU配下のアカウントに対してスタックが自動展開、 Lambdaが実行されます。 この Lambda によって Security Hub の更新(コントロール無効化/有効化)を行います。
CFnテンプレートを作ってみる
以下リソースを作成する CFnテンプレートを書きます。
リソース名 | タイプ | 備考 |
---|---|---|
UpdateControls |
カスタムリソース | UpdateControlsLambdaFunction を呼び出す |
LambdaExecutionRole |
IAMロール | UpdateControlsLambdaFunction の実行ロール |
UpdateControlsLambdaFunction |
Lambda関数 | 指定したコントロールを無効化(有効化) する |
以下にCFnテンプレートを置いています。利用される場合は活用ください。
インプットについて
インプットとして AFSBPDisableList
と AFSBPEnableList
を使用します。
『基礎セキュリティのベストプラクティス』のコントロールIDを(カンマ区切りで) それぞれに書いていきます。
AFSBPDisableList
- 無効化したいコントロールIDのリストです
- 例:
IAM.6,IAM.2,EC2.10,CloudTrail.5,S3.5
AFSBPEnableList
- 有効化したいコントロールIDのリストです (無効化したけど再度有効化したいときに使います)
- 例:
CloudTrail.1,RDS.1,EC2.19
(参考) Lambda関数のコード
以下に Lambda関数のコード部分を抜粋します。
update_securityhub_controls 関数
がメインです。
ここで指定したコントロールIDを無効化(および有効化) します。
試してみる
特定OUにこの CFnテンプレートのスタックセットを作成します。 メンバーアカウントをこのOUに所属させて Security Hub のコントロールが更新されるかどうか確かめます。
スタックセット作成
適当に作成している MemberOU
にスタックセットを仕込みます。
まずはスタックセットを作成します。
以下は IAM.5,APIGateway.3,CloudTrail.2,EC2.4,RDS.7,RDS.8
を無効化する例です。
TEMPLATE_PATH=(テンプレートのパス) STACKSET_NAME="InitialSetup-SecurityHubAFSBPControls" AFSBPDisableList="IAM.5,APIGateway.3,CloudTrail.2,EC2.4,RDS.7,RDS.8" AFSBPEnableList="" # スタックセット作成 aws cloudformation create-stack-set \ --stack-set-name "${STACKSET_NAME}" \ --template-body file://${TEMPLATE_PATH} \ --permission-model SERVICE_MANAGED \ --auto-deployment Enabled=true,RetainStacksOnAccountRemoval=false \ --capabilities CAPABILITY_IAM CAPABILITY_NAMED_IAM \ --parameters "[ { \"ParameterKey\": \"AFSBPDisableList\", \"ParameterValue\": \"${AFSBPDisableList}\" }, { \"ParameterKey\": \"AFSBPEnableList\", \"ParameterValue\": \"${AFSBPEnableList}\" } ]"
次にスタックインスタンスを作ります。
STACKSET_NAME="InitialSetup-SecurityHubAFSBPControls" # OU IDの指定(複数ある場合はカンマ区切り) OU_ID="ou-xxxx-example" # スタックインスタンス作成 # (※注意) 以下の例は --regions に全てのリージョンを指定しています。 # 稼働している Security Hub のリージョンを絞っている場合は、それに合わせてください aws cloudformation create-stack-instances \ --stack-set-name "${STACKSET_NAME}" \ --deployment-targets OrganizationalUnitIds=${OU_ID} \ --regions eu-north-1 ap-south-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-3 ap-northeast-2 ap-northeast-1 sa-east-1 ca-central-1 ap-southeast-1 ap-southeast-2 eu-central-1 us-east-1 us-east-2 us-west-1 us-west-2 \ --operation-preferences RegionConcurrencyType=PARALLEL
以下のようなスタックセットができました( MemberOU にはまだアカウントを所属させていないのでスタックインスタンスは無い)。
アカウントを移動させてみる
メンバーアカウントを MemberOU
へ移動させます。
移動後にスタックセットを確認します。自動で CREATE オペレーションが開始されていました。 アカウントの各リージョンにスタックインスタンスが作成されています。
▼ すべて CURRENT になったら OKです
このメンバーアカウントの Security Hubを確認します。 (ほぼノータッチの) ムンバイリージョンに訪れてみました。
IAM.5,APIGateway.3,CloudTrail.2,EC2.4,RDS.7,RDS.8
が無効化されていること確認できました。
▼ CloudWatch Logs にて実行ログを確認できます
無効化したものを有効化する
- 追加で
RDS.19,RDS.20,RDS.21,RDS.22
を無効化する - やっぱり
RDS.7,RDS.8
は有効化する
上記更新を先程のスタックセットに反映させてみます。
TEMPLATE_PATH=(テンプレートのパス) STACKSET_NAME="InitialSetup-SecurityHubAFSBPControls" # 追加で RDS.19,RDS.20,RDS.21,RDS.22 を無効化する AFSBPDisableList="IAM.5,APIGateway.3,CloudTrail.2,EC2.4,RDS.19,RDS.20,RDS.21,RDS.22" # やっぱり RDS.7,RDS.8 は有効化する AFSBPEnableList="RDS.7,RDS.8" # スタックセット更新 aws cloudformation update-stack-set \ --stack-set-name "${STACKSET_NAME}" \ --use-previous-template \ --capabilities CAPABILITY_IAM CAPABILITY_NAMED_IAM \ --operation-preferences RegionConcurrencyType=PARALLEL \ --parameters "[ { \"ParameterKey\": \"AFSBPDisableList\", \"ParameterValue\": \"${AFSBPDisableList}\" }, { \"ParameterKey\": \"AFSBPEnableList\", \"ParameterValue\": \"${AFSBPEnableList}\" } ]"
UPDATE オペレーションの完了後に再度 メンバーアカウントの Security Hubを確認します。
RDS.19,RDS.20,RDS.21,RDS.22
が追加で無効化されていること確認できました。
RDS.7,RDS.8
が再び有効化されていることも確認できました。
▼ (参考) CloudWatch Logs のログ抜粋
[INFO] 2021-10-(略) 7582(略)7ad2a disabling controls... [INFO] 2021-10-(略) 7582(略)7ad2a IAM.5 is already disabled, or not exist [INFO] 2021-10-(略) 7582(略)7ad2a APIGateway.3 is already disabled, or not exist [INFO] 2021-10-(略) 7582(略)7ad2a CloudTrail.2 is already disabled, or not exist [INFO] 2021-10-(略) 7582(略)7ad2a EC2.4 is already disabled, or not exist [INFO] 2021-10-(略) 7582(略)7ad2a disabling RDS.19 [INFO] 2021-10-(略) 7582(略)7ad2a disable successfully [INFO] 2021-10-(略) 7582(略)7ad2a disabling RDS.20 [INFO] 2021-10-(略) 7582(略)7ad2a disable successfully [INFO] 2021-10-(略) 7582(略)7ad2a disabling RDS.21 [INFO] 2021-10-(略) 7582(略)7ad2a disable successfully [INFO] 2021-10-(略) 7582(略)7ad2a disabling RDS.22 [INFO] 2021-10-(略) 7582(略)7ad2a disable successfully [INFO] 2021-10-(略) 7582(略)7ad2a enabling controls... [INFO] 2021-10-(略) 7582(略)7ad2a enabling RDS.7 [INFO] 2021-10-(略) 7582(略)7ad2a enable successfully [INFO] 2021-10-(略) 7582(略)7ad2a enabling RDS.8 [INFO] 2021-10-(略) 7582(略)7ad2a enable successfully
おわりに
CFnスタックセットのOrganizations 連携、および Lambda-backed カスタムリソースを 組み合わせた Security Hub における活用例でした。
今回は『基礎セキュリティのベストプラクティス』のみの対応ですが、 コード/テンプレートを少し修正するだけで CISなど他のセキュリティ基準にも対応できると思います。
Organizations環境で Security Hub のコントロール無効化/有効化周りの作業 に辛さを感じている人の参考になれば幸いです。